//(function(){
// # hanguage

// #### 介绍
// 目标：符系技术路线的汉语实现---H语言；
// - 本案以node.js宿主环境为例，尝试建立汉语版的符系系统“词典”（即：系统预设的中文关键词、符号）示范；
// - 详见readme文件声明。

// #### 软件架构
// 软件架构说明


// #### 安装教程

// 1.  xxxx
// 2.  xxxx
// 3.  xxxx

// #### 使用说明（唯一且关键的呼吁与声明）：
// ##### 鉴于---
// 1. 符系风格对人类所有语言文字更天然友好；
// 2. 汉语在实现该技术路线上的显见的优越性；
// 3. 已有或将来的中文符系运用应尽可能有公认的标准，力避无益的“方言”。
// ##### 倡议并声明：
// 1. 不论是在硬件还是在不同宿主环境下，不同人实现的中文符系运用应予采纳本“词典”的具体字词和符号；
// 2. 在具体字词、符号及流程控制的汉语表达习惯上，何为准确、完美，或者说“标准”，对于不同人，不可避免地有各种理解，欢迎参与讨论和建议；
// 3. 暂时有明显争议的，本案将在两可之中自行决定；
// 4. 有关讨论和建议，本案与同好将力争达成共识，未能形成共识的，本案将予以收集整理于本声明的*附注*之中，并尽量提供讨论、投票的平台，以期达成最大程度的共识。

// ##### 附注：
// 1. *符系（符式）*：关于 “forth” 一词的理解和翻译，本案认为：皆可，但倾向采用：“符系”一词；
// 2. *S、$、J、T*：台湾符系圈（组织）有符系“8大将”的形象说法，指：dup、push、swap、drop...等，大陆有人采用等”∵、∴、§“符号意图形象代之，其实颇显突兀，本案建立“四类操作”的概念。
// 3. *是则 否则 然后* ：
// 4. swith类：
// 4.1 *若是 则 或是 则 或者 则。* ：
// 4.2 *若是 则 或是 则 或则。* ：
// 4.3 *若是 则 或是 则 或则$* ：
// 5. *起 本次 下起* ：
// 6. *次 本次 再次* ：
// #### 参与贡献

// 1.  Fork 本仓库
// 2.  新建 Feat_xxx 分支
// 3.  提交代码
// 4.  新建 Pull Request


// #### 特技

// 1.  使用 Readme\_XXX.md 来支持不同的语言，例如 Readme\_en.md, Readme\_zh.md
// 2.  Gitee 官方博客 [blog.gitee.com](https://blog.gitee.com)
// 3.  你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解 Gitee 上的优秀开源项目
// 4.  [GVP](https://gitee.com/gvp) 全称是 Gitee 最有价值开源项目，是综合评定出的优秀开源项目
// 5.  Gitee 官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help)
// 6.  Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)
// 丈、尺、分、厘、毫、丝、忽、微、纤、沙、尘（奈、纳[2]）、埃、渺、漠（皮）...
if (!global.cn) {
    cn = {};
}
cn.cpu = function() {
    var 寄存组 = [], // 也是一个堆栈。我也称之为：参数栈。
        暂存组 = [],执行IP = 0, // 暂存组 (return stack)由系统或用户存放返回地址等
        内存组 = [],内存IP = 0, // 好比是开机必载之bios、os之类的，系统“词典”和用户新定义的指令（“词”）一并不妨视为：机器实体之内存。
        词典 = {}, // 词典{词名:function(),...} 基于机器实体对词典内指令（“词”）的构造麻烦些，我们基于node或其它环境，当然取便利之径。
        词册 = [], // 好比是将词典分册印制，分以把控，不致互扰。
        当前册名 = "horth", // horth意味着汉语(hanguage's forth)
        隶属册名 = "horth",
        cpu = this;
    // 如上，大致就是我们在node环境下对拟设计对符系虚拟机的硬件。
    // 当然，也可以利用 ArrayBuffer(或new Buffer(cpu);) 正儿八经地从一单元64位之类地从每个开关电路开始模拟设计我们地符系实体机。
    // 留待下一步看情况吧。如有人想尝试，个人最为感谢并最推荐的是多年前拜读过的台湾丁陈汉荪所著《嵌入式系统--使用eForth》这本书！
    // 其它可了解（链接可能失效）：
    //      1、Starting Forth  https://www.forth.com/starting-forth/
    //      2、Thinking Forth  http://thinking-forth.sourceforge.net/
    // 印象中，受forth群高手指点，本人长期以来曾从沈志斌版、win32forth、gforth、eforth、jeforth、j3weforth、8th、...以及github上基于php、python、JavaScript、c、ruby等实现的示例，粗浅了解和参考学习了不少

    // 符系即堆栈式计算机的技术路线，它内设两大寄存组（）
    cpu.寄存组 = {
        push: function(data, index) {
            switch (arguments.length) {
                case 0:
                    console.log(" push() what?\n");
                case 1:
                    寄存组.push(data);
                    break;
                default:
                    if (index >= 寄存组.length) {
                        寄存组.unshift(data);
                    } else {
                        寄存组.splice(寄存组.length - 1 - index, 0, data);
                    }
            }
        },
        drop: function(index) { // 删除
            switch (arguments.length) {
                case 0:
                    return 寄存组.pop();
                default:
                    return 寄存组.splice(寄存组.length - 1 - index, 1)[0];
            }
        },
        swap: function(index1, index2) { // 交换。
            // 在位置 2，添加 3 个元素，删除 1 个元素：fruits.splice(2, 1, "Lemon", "Kiwi","ccc");
            var tmp1, tmp2;
            switch (arguments.length) {
                case 0:
                    tmp1 = pop(1);
                    push(tmp1);
                    break; // 无参数则默认：冠亚（顶次二项）对调  寄存组.splice(寄存组.length-1-index, 1)
                case 1:
                    if (index1 >= 0) { // 后n#置顶
                        tmp1 = pop(index1);
                        push(tmp1);
                    } else { // 负数表示顶#后移
                        tmp1 = pop();
                        push(tmp1, -index1 - 1);
                    }
                    break; // 参数n，则默认: n # 置顶
                default:
                    tmp1 = tos(index1);
                    tmp2 = tos(index2);
                    寄存组.splice(寄存组.length - 1 - index1, 1, tmp2);
                    寄存组.splice(寄存组.length - 1 - index2, 1, tmp1);
            }
        },
        zrop: function(topn) { // 整组drop；无返回值
            switch (arguments.length) {
                case 0:
                    寄存组 = []; // 无参数则默认整组删除
                default:
                    寄存组.splice(寄存组.length - 1 - topn);
            }
        },
        all: function() {
            return 寄存组;
        },
        tos: function() {
            return 寄存组[寄存组.length - 1]
            // console.log(" push() what?\n");
        },
        全$: function() { // 全部删除
            寄存组 = [];
        }
    }

    // 临时手工预设词典内置指令（ 词）：
    词典 = {
        "+": function() {
            cpu.寄存组.push(寄存组.pop() + 寄存组.pop());
        },
        "-": function() {
            var b = 寄存组.pop()
            cpu.寄存组.push(寄存组.pop() - b);
        }
    }
    cpu.词典 = { //设置词典的查找等操作
        令: function 查典取词(name) {
            // defined in project-k projectk.js 
            return 词典[name] || 0; // 0 means 'not found'
        }
    }

    return cpu;
};


cn.vm = function() { // 以node.js为宿主机所建立的“符系”即时执译虚拟机（区别于repl，如此称谓和定义也远比“堆栈式”计算机来得准确！）
    var vm = this;
    // console.log(cn.cpu().内存IP);
    var cpu = new cn.cpu();
    // console.log(newcpu.内存IP);
    vm.prompt = ">>>";
    vm.stdio = require('readline').createInterface({
        input: process.stdin,
        output: process.stdout
    });
    vm.stdio.setPrompt(' ' + vm.prompt + ' ', 4);
    vm.执译不已 = function(cmd) {
        var arr = cmd.trim().toString().split(" "); // 经测试，最后会莫名多出一个空字符串"",
        // arr.pop(); // 所以，pop掉
        // console.log(arr);
        var len = arr.length,
            word;
        for (i = 0; i < len; i++) {
            word = arr[i];
            if (parseFloat(word).toString() == "NaN") { // 不是数值。isNaN()函数 把空串 空格 以及NUll 按照0来处理 
                //cpu.寄存组.push(word);
                if (cpu.词典.令(word)) {
                    //cpu.寄存组.push(cpu.词典.令(word));
                    cpu.词典.令(word)();
                    // word();
                } else {
                    // 不明指令或无法执译的情况处理
                }
            } else {
                cpu.寄存组.push(parseFloat(word));
                //console.log(arr);
            }
        }
        console.log(cpu.寄存组.all());
        vm.stdio.prompt(); // 定义于后

        // function isNumber(val) {
        //     var regPos = /^\d+(\.\d+)?$/; //非负浮点数
        //     var regNeg =
        //         /^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$/; //负浮点数
        //     if (regPos.test(val) && regNeg.test(val)) {
        //         return true;
        //     } else {
        //         return false;
        //     }
        // }

        // cpu.寄存组.push(2);
        // console.log(cpu.寄存组.tos());
        // console.log(cpu.寄存组.all());
    }
    
    // 不妨将以下理解为该虚拟机的CPU时钟振荡器：
    vm.stdio.prompt();
    vm.stdio.on('line', vm.执译不已);
};
//})();
cn.vm();
